package rewardsonline.config;

import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

/**
 * TODO-02a: Annotate this class with the proper annotation to enable security.
 * Save all work and restart the server. You should be able to access
 * the home page, but you should get a 404 when clicking on "Accounts" 
 * due to a redirect to: http://localhost:8080/TO-DO-03. The system 
 * needs you to login, but we have not configured that yet. Before fixing that
 * review some useful definitions below - see TO-DO-02b
 */
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
	
	/**
	 * To logout at any time prior to TO DO 07, use this link:
	 * http://localhost:8080/logout
	 */
	
	
	/**
	 * TODO-03: Set the login page so it uses '/login' and the access denied page so it uses '/denied'.
	 * Check the username/password of the user defined in the below configure method and
	 * use it to log into the application. 
	 * This user is not allowed to access the 'Account Search' page yet so,
	 * after log in, you should expect to see access denied to this page.
	 */
	
	/**
	 * TODO-04: Logout, then try to log in using incorrect user/password such as 'foo', 'foo'. You should 
	 * get a 404 error (file not found) because we have not set up an invalid login page.
	 * In this case, we want to be redirected to '/login?login_error=1'. 
	 * Update formLogin() below and set the failureUrl().
	 * Re-run the application and try logging in again by using an incorrect username/password.
	 * Look at login.jsp to see how it handles the login_error parameter.
	 */
	
	/**
	 * TODO-05: As defined below, users with role ROLE_EDITOR can already access '/accounts/*'. 
	 * Update the configuration so users with role ROLE_VIEWER can also access that same URL pattern.
	 * After completing this task, re-run the web application. User 'vince' should now be
	 * able to access the account search, display some accounts and view individual accounts.
	 * But not Edit. Try doing a search, click on the first account in the results list
	 * and then click on the Edit link - you will get Access Denied again.
	 */
	
	/**
	 * TODO-06: Add a logout link to the standard.jsp (see the TO DO in that file) by copying it
	 * from denied.jsp (see TO DO in that file also).
	 * Log out by clicking on the 'log out' link. Notice the link disappears.
	 * It reappears if you login again (click on Accounts to force a login).
	 *
	 * Logout once more and then try to access
	 * 'http://localhost:8080/accounts/hidden/page'.
	 * 
	 * As you can see, this URL is not currently protected.
	 * Add a matcher for /accounts/** (see below). For this pattern, all users should be
	 * authenticated (no specific role required). Try to access this URL again and you should
	 * now be redirected to the login page. Once logged in, you are redirected to the hidden page
	 * successfully.
	 */
	
	/**
	 * TODO-08: See corresponding instructions in WEB-INF/accounts/show.jsp
	 */
	
	/**
	 * TODO-09: See corresponding instructions in WEB-INF/accounts/show.jsp
	 */	
	
	@Override
	protected void configure(HttpSecurity http) throws Exception {
		
		http.csrf().disable();
		
		/**
		 * TODO-06c: Add restriction for /accounts/**
		 */
		http
	        .authorizeRequests()
	        	.antMatchers("/styles/**", "/images/**", "/logout", "/login", "/denied", "/home", "/").permitAll()
	        	.antMatchers("/accounts/*/edit*").access("hasRole('ROLE_EDITOR')")
	        	.antMatchers("/accounts/*").access("hasRole('ROLE_EDITOR')")
	        	.and()
	        .formLogin()
	            .loginPage("/TODO-03")
	            .permitAll()
	            .failureUrl("/TODO-04")
	            .and()
	        .logout()
	        	.logoutUrl("/logout")
	        	.logoutSuccessUrl("/home")
	            .permitAll()
	            .and()
	        .exceptionHandling().accessDeniedPage("/TODO-03");
	}
	
	@Override
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
		
		/**
		 * TODO-07: Add a user edith/edith with role 'ROLE_EDITOR'.
		 * Be careful with the syntax, the method automatically prefixes each entry with "ROLE_".
		 * Re-run the web application. If you don't see the log in form, log out from the application by 
		 * clicking on the "log out" link.
		 * You can now log in with the user 'edith'. On the 'Account details' page, you should
		 * see the link "(Edit)". By clicking on it, you will be able to edit account details.
		 * Try to log in again using 'vince' and double-check that vince, who only has 'VIEWER' rights,
		 * is still not allowed to edit account information.
		 */
		
		/**
		 * TODO-10: Optional Bonus: inside the AuthenticationManagerBuilder, improve security by using encryption.
		 */
		
		/**
		 * TODO-11: Optional Bonus 1: Add a new user called 'admin' with password 'spring' and full privileges
		 * (all roles).
		 */
		
		/**
		 * TODO-12: Optional Bonus 2: At this stage, passwords declared in this file are not encoded. You can find
		 * encoded versions of them below.  For each of the users declared at the beginning of this file,
		 * replace the password with the encoded version.
		 *
		 * Encoded version of vince is 08c461ad70fce6c71a9a8e0f824a2f9f54a69db58679f095ea541b2b2419af91
		 * Encoded version of edith is 4cfbf05e4493d17167dbd8ae46b1248d3f3b41ff517bcf60b25bff8a5b206f8c
		 * Encoded version of spring is 622a494d3ea8c7ba2fed4f37909f14d9b50ab412322de39be62c8d6c2418bfca
		 *
		 * Now add password encoding option below. After that, re-run
		 * the web application and try logging in again.
		 *
		 * If you'd like to generate another sha-256-encoded password, there are many generators available online 
		 * such as this one: http://www.technipixel.com/webapps/hashencoder.htm
		 *
		 * Please note this is a simple demo only.  Strong password encryption is hard to achieve - see
		 * the solution for more details.
		 */
		
		auth.inMemoryAuthentication()
				.withUser("vince").password("vince").roles("VIEWER");
	}
}
